use cgmath::{vec3, Vector2, Vector3, Vector4};
use wgpu::vertex_attr_array;

use crate::Vertex;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex2D {
    position: Vector2<f32>,
}

impl Vertex for Vertex2D {
    const ATTRS: &'static [wgpu::VertexAttribute] = &vertex_attr_array![0 => Float32x2];
}

pub fn v2d(position: Vector2<f32>) -> Vertex2D {
    Vertex2D { position }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex2DC {
    position: Vector2<f32>,
    color: Vector4<f32>,
}

impl Vertex for Vertex2DC {
    const ATTRS: &'static [wgpu::VertexAttribute] =
        &vertex_attr_array![0 => Float32x2, 1 => Float32x4];
}

pub fn v2dc(position: Vector2<f32>, color: Vector4<f32>) -> Vertex2DC {
    Vertex2DC { position, color }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex2DU {
    position: Vector2<f32>,
    uv: Vector2<f32>,
}

impl Vertex for Vertex2DU {
    const ATTRS: &'static [wgpu::VertexAttribute] =
        &vertex_attr_array![0 => Float32x2, 1 => Float32x2];
}

pub fn v2du(position: Vector2<f32>, uv: Vector2<f32>) -> Vertex2DU {
    Vertex2DU { position, uv }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex2DCU {
    position: Vector2<f32>,
    color: Vector4<f32>,
    uv: Vector2<f32>,
}

impl Vertex for Vertex2DCU {
    const ATTRS: &'static [wgpu::VertexAttribute] =
        &vertex_attr_array![0 => Float32x2, 1 => Float32x4, 2 => Float32x2];
}

pub fn v2dcu(position: Vector2<f32>, color: Vector4<f32>, uv: Vector2<f32>) -> Vertex2DCU {
    Vertex2DCU {
        position,
        color,
        uv,
    }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex3D {
    position: Vector3<f32>,
}

impl Vertex for Vertex3D {
    const ATTRS: &'static [wgpu::VertexAttribute] = &vertex_attr_array![0 => Float32x3];
}

pub fn v3d(position: Vector3<f32>) -> Vertex3D {
    Vertex3D { position }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex3DC {
    position: Vector3<f32>,
    color: Vector4<f32>,
}

impl Vertex for Vertex3DC {
    const ATTRS: &'static [wgpu::VertexAttribute] =
        &vertex_attr_array![0 => Float32x3, 1 => Float32x4];
}

pub fn v3dc(x: f32, y: f32, z: f32, color: Vector4<f32>) -> Vertex3DC {
    Vertex3DC {
        position: vec3(x, y, z),
        color,
    }
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vertex3DU {
    position: Vector3<f32>,
    uv: Vector2<f32>,
}

impl Vertex for Vertex3DU {
    const ATTRS: &'static [wgpu::VertexAttribute] =
        &vertex_attr_array![0 => Float32x3, 1 => Float32x2];
}

pub fn v3du(position: Vector3<f32>, uv: Vector2<f32>) -> Vertex3DU {
    Vertex3DU { position, uv }
}
